﻿namespace Neovolve.Bootstrapper.Wizard
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Windows.Forms;
    using EnvDTE;
    using Microsoft.VisualStudio.TemplateWizard;

    /// <summary>
    /// The <see cref="TemplateConfiguration"/>
    ///   class provides the ability to customise the bootstrapper project template.
    /// </summary>
    public class TemplateConfiguration : IWizard
    {
        /// <summary>
        /// Stores the name of the project related to the project being created.
        /// </summary>
        private String _dependentProjectName;

        /// <summary>
        /// Runs custom wizard logic before opening an item in the template.
        /// </summary>
        /// <param name="projectItem">
        /// The project item that will be opened.
        /// </param>
        public void BeforeOpeningFile(ProjectItem projectItem)
        {
        }

        /// <summary>
        /// Runs custom wizard logic when a project has finished generating.
        /// </summary>
        /// <param name="project">
        /// The project that finished generating.
        /// </param>
        public void ProjectFinishedGenerating(Project project)
        {
            if (project == null)
            {
                return;
            }

            if (String.IsNullOrWhiteSpace(_dependentProjectName))
            {
                return;
            }

            IList<Project> deploymentProjects = project.DTE.DeploymentProjects();
            Project linkedProject = deploymentProjects.Single(x => x.Name == _dependentProjectName);
            BuildDependency dependency = project.DTE.Solution.SolutionBuild.BuildDependencies.Item(project.UniqueName);

            dependency.AddProject(linkedProject.UniqueName);
        }

        /// <summary>
        /// Runs custom wizard logic when a project item has finished generating.
        /// </summary>
        /// <param name="projectItem">
        /// The project item that finished generating.
        /// </param>
        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
        }

        /// <summary>
        /// Runs custom wizard logic when the wizard has completed all tasks.
        /// </summary>
        public void RunFinished()
        {
        }

        /// <summary>
        /// Runs custom wizard logic at the beginning of a template wizard run.
        /// </summary>
        /// <param name="automationObject">
        /// The automation object being used by the template wizard.
        /// </param>
        /// <param name="replacementsDictionary">
        /// The list of standard parameters to be replaced.
        /// </param>
        /// <param name="runKind">
        /// A <see cref="T:Microsoft.VisualStudio.TemplateWizard.WizardRunKind"/> indicating the type of wizard run.
        /// </param>
        /// <param name="customParams">
        /// The custom parameters with which to perform parameter replacement in the project.
        /// </param>
        public void RunStarted(
            Object automationObject, Dictionary<String, String> replacementsDictionary, WizardRunKind runKind, Object[] customParams)
        {
            if (replacementsDictionary == null)
            {
                throw new ArgumentNullException("replacementsDictionary");
            }

            DTE dte = automationObject as DTE;

            String destinationDirectory = replacementsDictionary["$destinationdirectory$"];

            try
            {
                using (PackageDefinition definition = new PackageDefinition(dte, destinationDirectory))
                {
                    DialogResult dialogResult = definition.ShowDialog();

                    if (dialogResult != DialogResult.OK)
                    {
                        throw new WizardBackoutException();
                    }

                    replacementsDictionary.Add("$packagePath$", definition.PackagePath);
                    replacementsDictionary.Add("$packageExtension$", Path.GetExtension(definition.PackagePath));

                    _dependentProjectName = definition.SelectedProject;
                }
            }
            catch (Exception ex)
            {
                // The wizard has been canceled
                // Clean up the template that was written to disk
                if (Directory.Exists(destinationDirectory))
                {
                    Directory.Delete(destinationDirectory, true);
                }

                Debug.WriteLine(ex);

                throw;
            }
        }

        /// <summary>
        /// Indicates whether the specified project item should be added to the project.
        /// </summary>
        /// <param name="filePath">
        /// The path to the project item.
        /// </param>
        /// <returns>
        /// True if the project item should be added to the project; otherwise, false.
        /// </returns>
        public Boolean ShouldAddProjectItem(String filePath)
        {
            return true;
        }
    }
}